home *** CD-ROM | disk | FTP | other *** search
- #include "MyHeader.h"
- #include "ShieldRect.h"
-
- //
-
- #define textureSize 128
- #define textureCount 5
- #define maxEngines 10
- #define textHeight 15
-
- #define boundrySlop 0.1
-
- #define ClipUpper(f, upperLimit) {if((f) > (upperLimit)) (f) = (upperLimit);}
-
- #define ClampDifuseColor(v) {ClipUpper((v)->kd_r, 1.0); ClipUpper((v)->kd_g, 1.0); ClipUpper((v)->kd_b, 1.0);}
-
- // Local Prototypes
- static GWorldPtr LoadPicture(short resID);
- static TQAError SetTextureByNumber(MyState * state, short textureNumber);
- static void DrawObject(MyState *state, MyObject * object, short doShading);
- static void ClipZ(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3);
- static void ConvertTo2D(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3);
- static void ClipLeftBound(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3);
- static void ClipRightBound(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3);
- static void ClipTopBound(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3);
- static void ClipBottomBound(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3);
- static void MyDrawTriTexture(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3);
- static void MyTQAVTextureClip(TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3, float weight);
- static void SetupDrawContext(MyState *state);
- static void RectToTQARect(Rect * r, TQARect * r2);
- static void DeleteDrawContext(MyState *state);
- static RgnHandle CalcGlobalVisRgn(MyState *state);
-
- // vars
- static TQAEngine *gEngineList[maxEngines];
- static long gEngineCount;
-
- static MyVector xVector = {1, 0, 0};
- static MyVector yVector = {0, 1, 0};
- MyObject ob1, ob2, ob3, ob4;
- TQATexture * textureList[maxEngines][textureCount];
-
- GWorldPtr gwList[textureCount];
-
- // Code
-
- void UpdateMyMenus(WindowPtr w)
- {
- MyState * state;
- long x;
- MenuHandle mh;
-
-
- state = (MyState*)GetWRefCon(w);
-
- mh = GetMenuHandle(engineMenuID);
- for(x = 0; x < gEngineCount; x++){
- SetItemMark(mh, x + 1, state->engineNumber == x ? checkMark : noMark);
- }
-
- mh = GetMenuHandle(optionsMenuID);
- SetItemMark(mh, 1, state->doubleBuffer ? checkMark : noMark);
- SetItemMark(mh, 2, state->noZBuffer ? checkMark : noMark);
- SetItemMark(mh, 3, state->perspectiveZ ? checkMark : noMark);
- SetItemMark(mh, 4, state->useMemoryDevice ? checkMark : noMark);
- SetItemMark(mh, 5, state->useTriMeshes ? checkMark : noMark);
-
- mh = GetMenuHandle(antialiasingMenuID);
- for(x = 0; x < 4; x++){
- SetItemMark(mh, x + 1, state->antialiasing == x ? checkMark : noMark);
- }
-
- mh = GetMenuHandle(textureFilterMenuID);
- for(x = 0; x < 3; x++){
- SetItemMark(mh, x + 1, state->textureFilter == x ? checkMark : noMark);
- }
-
-
- }
-
- static void SetEngine(MyState * state, long engineNumber)
- {
- Str255 s;
-
- /*****/
-
- state->engineNumber = engineNumber;
- state->engine = gEngineList[engineNumber];
-
- GetMenuItemText(GetMenuHandle(engineMenuID), engineNumber + 1, s);
- SetWTitle(state->window, s);
- }
-
-
- void MyTestSetup(void)
- {
- long x;
- Str255 engineName;
- long engineNameLength;
- TQAEngine *engine;
-
- /**************/
-
- // build the engine menu
- QAEngineEnable(kQAVendor_Apple, kQAEngine_AppleHW);
- gEngineCount = 0;
- for(engine = QADeviceGetFirstEngine(NULL); engine; engine = QADeviceGetNextEngine(NULL, engine)){
- gEngineList[gEngineCount] = engine;
- gEngineCount++;
-
- QAEngineGestalt(engine, kQAGestalt_ASCIINameLength, &engineNameLength);
- QAEngineGestalt(engine, kQAGestalt_ASCIIName, (char *)engineName + 1);
- engineName[0] = engineNameLength;
- AppendMenu(GetMenuHandle(engineMenuID), engineName);
- }
-
- for(x = 0; x < textureCount; x++){
- gwList[x] = LoadPicture(141 + x);
- }
-
- //WriteGlobe();
- //WriteCylinder();
-
- ob1.shape = MyShapeLoad("cylinder");
- MyShapeCalculateNormals(ob1.shape, 2);
- ob1.backfaceCulling = 1;
- ob1.alpha = 1;
-
- ob2.shape = MyShapeLoad("globe");
- MyShapeCalculateNormals(ob2.shape, 0);
- ob2.backfaceCulling = 0;
- ob2.alpha = 0.5;
-
- ob4.shape = MyShapeLoad("die");
- MyShapeCalculateNormals(ob4.shape, 0);
- ob4.backfaceCulling = 1;
- ob4.alpha = 1;
-
- ob3.shape = MyShapeLoad("floor");
- MyShapeCalculateNormals(ob3.shape, 1);
- ob3.alpha = 1;
-
- MyMatrixClear(&globalState.camera);
- globalState.camera.w.z -= 7;
-
-
- }
-
- void SetupNewWindow(void)
- {
- MyMatrix m;
- MyState *state;
-
- /**************/
-
- state = calloc(sizeof (MyState), 1);
- CheckMem(state);
-
- state->d = 0.1;
- state->h = state->d * 0.5;
- state->f = 100;
- state->ambient = 0.3;
- state->window = GetNewCWindow(128, NULL, (WindowPtr) -1);
- state->perspectiveZ = 1;
- state->doubleBuffer = 1;
- state->useTriMeshes = 1;
-
- SetPort(state->window);
- TextMode(srcXor);
- TextSize(9);
- TextFont(monaco);
- SetWRefCon(state->window, (long)state);
-
- SetEngine(state, 0);
- SetItemMark(GetMenuHandle(engineMenuID), 1, checkMark);
-
- SetupDrawContext(state);
-
- state->lightVector = yVector;
- MyMatrixSetRotateX(-0.5, &m);
- MyMatrixTransformVector(&m, &state->lightVector, &state->lightVector); // rotate the light slightly toward the camera
- MyMatrixSetRotateZ(-0.5, &m);
- MyMatrixTransformVector(&m, &state->lightVector, &state->lightVector);
-
- }
-
- void UnloadTextures(void)
- {
- long x, y;
- TQAEngine *engine;
-
- /********/
-
- for(y = 0; y < gEngineCount; y++){
- engine = gEngineList[y];
- for(x = 0; x < textureCount; x++){
- if(textureList[y][x]){
- QATextureDelete(engine, textureList[y][x]);
- }
- }
- }
-
- for(x = 0; x < textureCount; x++){
- if(gwList[x]){
- DisposeGWorld(gwList[x]);
- }
- }
- }
-
- static void DrawErrorMessage(MyState *state)
- {
- SetPort(state->window);
- EraseRect(&state->window->portRect);
- if(state->errorMessage){
- TETextBox(state->errorMessage, strlen(state->errorMessage), &state->window->portRect, teFlushDefault);
- }
- }
-
-
- static void DumpTriangles(MyState * state)
- {
- long x;
-
- /******/
-
- if(state->vList.count == 0) return; // nothing to draw
-
- QASubmitVerticesTexture(state->drawContext, state->vList.count, state->vList.list);
- state->vList.count = 0;
-
- for(x = 0; x < textureCount; x++){
- if(state->tList[x].count){ // make sure that there are triangles that use this texture
- SetTextureByNumber(state, x);
- //QASetPtr(state->drawContext, kQATag_Texture, state->textureList[x]);
- QADrawTriMeshTexture(state->drawContext, state->tList[x].count, state->tList[x].list);
- state->tList[x].count = 0;
- }
- }
- }
-
-
- // MyEqualRgn is about 3 times faster than EqualRgn on PPC
- #define MyEqualRgn(r1, r2) (!memcmp(*(r1), *(r2), (**(r1)).rgnSize))
-
- #if 0
- // elapsedTime is in seconds
- static void MoveCamera(MyState *state, float elapsedTime)
- {
- KeyMap theKeys;
-
- GetKeys(&theKeys)
- }
- #endif
-
-
- void DrawFrame(MyState *state)
- {
- Point mousy;
- MyMatrix m;
- char s[200];
-
- UnsignedWide startTime;
- UnsignedWide finishTime;
-
- float framesPerSecond;
-
- Rect r;
-
- /************/
-
- Microseconds(&startTime);
-
- if(!state->active){
- DrawErrorMessage(state);
- return;
- }
-
- // if we are drawing to a gdevice, check to see if the visable area changed
- // to make sure we don't draw over any other windows
- if(!state->useMemoryDevice){
- if(!MyEqualRgn(state->window->visRgn, state->visRegion)){
- WindowChanged(state->window);
- }
- }
-
- SetPort(state->window); // port must be set before LocalToGlobal is called
- GetMouse(&mousy);
- LocalToGlobal(&mousy);
-
- /* the camera */
- #if 0
- MyMatrixClear(&state->camera);
- MyMatrixSetRotateY((float)mousy.h / -100, &m);
- MyMatrixCat(&state->camera, &m, &state->camera);
- state->camera.w.z -= (float)mousy.v / 40 + 3;
- #endif
-
- if(!globalState.stopObjects){
- /* cylinder */
- MyMatrixClear(&ob1.pos);
- MyMatrixSetRotateY((float)TickCount() / 50, &m);
- MyMatrixCat(&ob1.pos, &m, &ob1.pos);
- MyMatrixSetRotateX((float)mousy.h / 200, &m);
- MyMatrixCat(&ob1.pos, &m, &ob1.pos);
- ob1.pos.w.z += sin((float)TickCount() / 150) * 0.5;
- ob1.pos.w.y += cos((float)TickCount() / 150) * 3;
-
- /* globe */
- MyMatrixClear(&ob2.pos);
- MyMatrixSetRotateY((float)TickCount() / 75, &m);
- MyMatrixCat(&ob2.pos, &m, &ob2.pos);
- MyMatrixSetRotateX((float)mousy.h / 160, &m);
- MyMatrixCat(&ob2.pos, &m, &ob2.pos);
- // MyMatrixScaleLocal(&ob2.pos, (sin((float)TickCount() / -160) + 1.1) * 3, &ob2.pos);
- ob2.pos.w.x += sin((float)TickCount() / -160) * 3;
- ob2.pos.w.y += cos((float)TickCount() / -160) * 3;
- ob2.pos.w.z -= 0.2;
-
- /* the floor and walls */
- MyMatrixClear(&ob3.pos);
- ob3.pos.w.y += -1.5;
-
- /* the die */
- MyMatrixClear(&ob4.pos);
- MyMatrixSetRotateY((float)TickCount() / 100, &m);
- MyMatrixCat(&ob4.pos, &m, &ob4.pos);
- MyMatrixSetRotateX((float)TickCount() / 20, &m);
- MyMatrixCat(&ob4.pos, &m, &ob4.pos);
- }
-
-
- if(!state->useTriMeshes){
- QARenderStart(state->drawContext, NULL, NULL);
- }
-
- state->triangleCount = 0;
- DrawObject(state, &ob1, true);
- DrawObject(state, &ob3, true);
- DrawObject(state, &ob4, true);
-
- DrawObject(state, &ob2, true); // this sould go last because it has transpearancy
-
- if(state->useTriMeshes){
- QARenderStart(state->drawContext, NULL, NULL);
- DumpTriangles(state);
- }
-
- QARenderEnd(state->drawContext, NULL);
-
- if(state->useMemoryDevice){
- QASync(state->drawContext);
- CopyBits(PortBits(state->backBuffer), PortBits(state->window), &state->viewRect, &state->viewRect, srcCopy, NULL);
- } else {
- state->needsSync = true;
- }
- Microseconds(&finishTime);
-
- framesPerSecond = 1000000.0 / (finishTime.lo - startTime.lo); // subtracting will cancel out any overflow in .hi
-
- sprintf(s, "%7.2f fps (%hdx%hd) (TriCount=%4ld) (%2x)",
- framesPerSecond,
- state->viewRect.right - state->viewRect.left,
- state->viewRect.bottom - state->viewRect.top,
- state->triangleCount,
- (int)globalState.unusedKey);
-
- r = state->window->portRect;
- r.top = r.bottom - textHeight;
- EraseRect(&r);
- MoveTo(5, r.bottom - 2);
- DrawText(s, 0, strlen(s));
- }
-
-
-
-
-
-
- void HandleOtherMenu(short menuID, short menuItem)
- {
- WindowPtr w;
- MyState * state;
- short newValue;
-
- /*****/
-
- w = FrontWindow();
-
- if(!w) return;
-
- state = (MyState*)GetWRefCon(w);
-
- switch(menuID){
- case engineMenuID:
- DeleteDrawContext(state);
- SetEngine(state, menuItem - 1);
- SetupDrawContext(state);
- break;
-
- case optionsMenuID:
- switch(menuItem){
- case 1:
- newValue = state->doubleBuffer = !state->doubleBuffer;
- break;
- case 2:
- newValue = state->noZBuffer = !state->noZBuffer;
- break;
- case 3:
- newValue = state->perspectiveZ = !state->perspectiveZ;
- break;
- case 4:
- newValue = state->useMemoryDevice = !state->useMemoryDevice;
- break;
- case 5:
- newValue = state->useTriMeshes = !state->useTriMeshes;
- break;
- }
- DeleteDrawContext(state);
- SetupDrawContext(state);
- break;
- case antialiasingMenuID:
- DeleteDrawContext(state);
- state->antialiasing = menuItem - 1;
- SetupDrawContext(state);
- break;
- case textureFilterMenuID:
- DeleteDrawContext(state);
- state->textureFilter = menuItem - 1;
- SetupDrawContext(state);
- break;
- }
-
- UpdateMyMenus(w);
- }
-
- void WindowChanged(WindowPtr theWindow)
- {
- MyState * state;
-
- ///////
-
- state = (MyState*)GetWRefCon(theWindow);
-
- DeleteDrawContext(state);
- SetupDrawContext(state);
- }
-
- void ClosingWindow(WindowPtr theWindow)
- {
- MyState * state;
-
- ///////
-
- state = (MyState*)GetWRefCon(theWindow);
- DeleteDrawContext(state);
- free(state);
- }
-
- static GWorldPtr LoadPicture(short resID)
- {
- PicHandle p;
- GWorldPtr gw;
- QDErr e;
- static Rect r = {0, 0, textureSize, textureSize};
- GDHandle tempGD;
- CGrafPtr tempPort;
- PixMapHandle pm;
-
- /*************/
-
- p = GetPicture(resID);
-
- e = NewGWorld(&gw, 16, &r, NULL, NULL, 0);
-
- if(e) return NULL;
-
- pm = GetGWorldPixMap(gw);
- LockPixels(pm);
-
- GetGWorld(&tempPort, &tempGD);
- SetGWorld(gw, NULL);
-
- EraseRect(&r);
- DrawPicture(p, &r);
- ReleaseResource((Handle)p);
-
- SetGWorld(tempPort, tempGD);
-
- return gw;
- }
-
- static TQAError SetTextureByNumber(MyState * state, short textureNumber)
- {
- PixMapHandle pm;
- TQAImage images[1];
- TQATexture * texture;
- TQAError err;
-
- /************/
-
- texture = textureList[state->engineNumber][textureNumber];
- if(texture == NULL){
- pm = GetGWorldPixMap(gwList[textureNumber]);
-
- images[0].width = textureSize;
- images[0].height = textureSize;
- images[0].rowBytes = (**pm).rowBytes & 0x3fff;
- images[0].pixmap = (**pm).baseAddr;
-
- err = QATextureNew(state->engine, 0, kQAPixel_RGB16, images, &texture);
- if(err){
- return err;
- }
-
- textureList[state->engineNumber][textureNumber] = texture;
- }
-
- QASetPtr(state->drawContext, kQATag_Texture, texture);
-
- }
-
-
-
-
-
- // see watt book p71 fig. 3.9
-
- /*
- note, specular calculation is a short cut.
- in real life vv would be different for each point.
- specular is just based on normal as if it were at center of object
- */
-
- static void DrawObject(MyState *state, MyObject * object, short doShading)
- {
- MyShape * shape = object->shape;
- long x, c, pn;
-
- MyVector v1, v2;
- MyVector n; // surface normal
- MyVector reflectionVector; // surface reflection vector
- MyVector lightSource; // camera relative light source vector
- MyVector toCamera; // view vector (from obj to cam)
-
- float difuse;
- float specular;
-
- TQAVTexture verts[3];
- TQAVTexture * v;
-
- MyMatrix r1;
-
- MyVector * points;
- MyVector * p;
- float * difs;
- float * specs;
-
- MyTri * tri;
-
- long previousTexture = -1;
- short backfacing;
-
- /***********/
-
-
-
- MyMatrixNegate(&globalState.camera, &r1);
- // state->camera is the position of the camera in world space.
- // r1 is now the position of the world in camera space
- MyMatrixCat(&object->pos, &r1, &r1); // r1 is now the position of the object relative to the camera and not the world
-
- if(r1.w.z + shape->maxDimention < state->d) return; // the object is completely behind the camera, dont bother drawing
-
- MYMALLOC(points, shape->pointCount);
- for(x = 0; x < shape->pointCount; x++){
- p = &points[x];
- MyMatrixTransformVector(&r1, &shape->pointList[x], p);
- }
-
-
- if(doShading){
- MYMALLOC(difs, shape->normalCount);
- MYMALLOC(specs, shape->normalCount);
-
- MyMatrixNegate(&object->pos, &r1);
- // r1 is world to object transform
- MyMatrixRotateVector(&r1, &state->lightVector, &lightSource); // lightSource is now the vector to the light relative to the object and not the world
- MyVectorSubtract(&globalState.camera.w, &object->pos.w, &toCamera); // toCamera is object center to camera in world space
- // note, this is a short cut.
- // more accurate to way is to calc per vertex
- MyMatrixRotateVector(&r1, &toCamera, &toCamera); // toCamera is now the vector to the camera in object space
- MyVectorNormalize(&toCamera, &toCamera); // normalized
-
- // this calculates the specular value on a per normal basis
- for(x = 0; x < shape->normalCount; x++){
-
- difuse = MyDotProduct(&lightSource, &shape->normalList[x]);
- // if(difuse < 0) difuse = 0;
-
- MyCalculateReflection(&lightSource, &shape->normalList[x], &reflectionVector);
- specular = MyDotProduct(&reflectionVector, &toCamera);
- if(specular < 0){
- specular = 0;
- } else {
- specular = pow(specular, 40);
- }
-
- difs[x] = difuse;
- specs[x] = specular;
- }
- }
-
-
- if(doShading){
- QASetInt(state->drawContext, kQATag_TextureOp, kQATextureOp_Modulate + kQATextureOp_Highlight);
- } else {
- QASetInt(state->drawContext, kQATag_TextureOp, 0);
- }
-
- if(object->alpha < 1){
- // state->saveTransTris = true;
- }
-
- for(x = 0; x < shape->triangleCount; x++){
- tri = &shape->triangleList[x];
-
-
- if(object->backfaceCulling || doShading){
- MyVectorSubtract(&points[tri->corner[1].pointNumber], &points[tri->corner[0].pointNumber], &v1);
- MyVectorSubtract(&points[tri->corner[2].pointNumber], &points[tri->corner[0].pointNumber], &v2);
- MyVectorCrossProduct(&v2, &v1, &n);
- backfacing = MyDotProduct(&points[tri->corner[0].pointNumber], &n) > 0;
- if(backfacing && object->backfaceCulling) continue;
- }
-
- if(shape->normalMode == 1){
- if(backfacing){
- difuse = -difs[shape->normalTable[x]];
- } else {
- difuse = difs[shape->normalTable[x]];
- }
- if(difuse < 0) difuse = 0;
- specular = specs[shape->normalTable[x]];
- }
-
- for(c = 0; c < 3; c++){
- pn = tri->corner[c].pointNumber;
- v = &verts[c];
- p = &points[pn];
-
- if(shape->normalMode == 0){
- if(backfacing){
- difuse = -difs[shape->normalTable[x * 3 + c]];
- } else {
- difuse = difs[shape->normalTable[x * 3 + c]];
- }
- if(difuse < 0) difuse = 0;
- specular = specs[shape->normalTable[x * 3 + c]];
- }
-
- v->x = p->x;
- v->y = p->y;
- v->z = p->z;
- v->uOverW = tri->corner[c].u;
- v->vOverW = tri->corner[c].v;
-
- v->r = v->g = v->b = 1;
- v->a = object->alpha;
-
- if(doShading){
- v->kd_r = v->kd_g = v->kd_b = difuse + state->ambient;
- v->ks_r = v->ks_g = v->ks_b = specular;
- } else {
- v->kd_r = v->kd_g = v->kd_b = 1;
- v->ks_r = v->ks_g = v->ks_b = 0;
- }
-
- }
-
- if(tri->texture != previousTexture){
- if(state->useTriMeshes){
- state->currentTList = &state->tList[tri->texture];
- } else {
- SetTextureByNumber(state, tri->texture);
- //QASetPtr(state->drawContext, kQATag_Texture, state->textureList[tri->texture]);
- }
- previousTexture = tri->texture;
- }
-
- ClipZ(state, &verts[0], &verts[1], &verts[2]);
-
- }
-
-
- free(points);
- if(doShading){
- free(difs);
- free(specs);
- }
- }
-
- #define CLIPX(p1, p2, p3, xBound) MyTQAVTextureClip(p1, p2, p3, (p2->x - xBound) / (p2->x - p1->x))
- #define CLIPY(p1, p2, p3, yBound) MyTQAVTextureClip(p1, p2, p3, (p2->y - yBound) / (p2->y - p1->y))
- #define CLIPZ(p1, p2, p3, zBound) MyTQAVTextureClip(p1, p2, p3, (p2->z - zBound) / (p2->z - p1->z))
-
-
- static void ClipZ(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3)
- {
- TQAVTexture ta, tb;
- float bound = state->d + boundrySlop;
-
- /***/
-
- if(v1->z < bound){
- if(v2->z < bound){
- if(v3->z < bound){
- // all points are out of bounds, draw nothing
- return;
- } else {
- // 1 & 2 are out
- CLIPZ(v1, v3, &ta, bound);
- CLIPZ(v2, v3, &tb, bound);
- ConvertTo2D(state, &ta, &tb, v3);
- }
- } else {
- if(v3->z < bound){
- // 1 & 3 are out
- CLIPZ(v1, v2, &ta, bound);
- CLIPZ(v3, v2, &tb, bound);
- ConvertTo2D(state, &ta, &tb, v2);
- } else {
- // 1 is out
- CLIPZ(v1, v2, &ta, bound);
- CLIPZ(v1, v3, &tb, bound);
- ConvertTo2D(state, &ta, v2, v3);
- ConvertTo2D(state, &tb, &ta, v3);
- }
-
- }
- } else {
- if(v2->z < bound){
- if(v3->z < bound){
- // 2 & 3 are out
- CLIPZ(v2, v1, &ta, bound);
- CLIPZ(v3, v1, &tb, bound);
- ConvertTo2D(state, &ta, &tb, v1);
- return;
- } else {
- // 2 is out
- CLIPZ(v2, v1, &ta, bound);
- CLIPZ(v2, v3, &tb, bound);
- ConvertTo2D(state, &ta, v1, v3);
- ConvertTo2D(state, &tb, &ta, v3);
- }
- } else {
- if(v3->z < bound){
- // 3 is out
- CLIPZ(v3, v1, &ta, bound);
- CLIPZ(v3, v2, &tb, bound);
- ConvertTo2D(state, &ta, v1, v2);
- ConvertTo2D(state, &tb, &ta, v2);
- } else {
- // all are in
- ConvertTo2D(state, v1, v2, v3);
- }
- }
- }
- }
-
-
- static void ConvertTo2D(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3)
- {
- float iw;
- TQAVTexture * v;
- TQAVTexture verts[3]; // must use a local copy because values are modified
- long c;
-
- float pixelConversion = (state->d / state->h) * (-state->viewWidth / 2);
-
- verts[0] = *v1;
- verts[1] = *v2;
- verts[2] = *v3;
-
- for(c = 0; c < 3; c++){
- v = &verts[c];
-
- iw = 1.0 / v->z;
-
-
-
- v->x = v->x * iw * pixelConversion + (state->viewWidth/2);
- v->y = v->y * iw * pixelConversion + (state->viewHeight/2);
- v->z = (v->z * (state->f / (state->f - state->d)) + (-state->f * state->d / (state->f - state->d))) * iw;
- // v->z = v->z / state->f;
- // v->z = 0.5;
-
- v->invW = iw;
- // v->invW = 1.0;
- v->uOverW *= iw;
- v->vOverW *= iw;
- }
-
- ClipLeftBound(state, &verts[0], &verts[1], &verts[2]);
- }
-
-
- static void ClipLeftBound(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3)
- {
- TQAVTexture ta, tb;
- float bound = 0 + boundrySlop;
-
- /***/
-
- if(v1->x < bound){
- if(v2->x < bound){
- if(v3->x < bound){
- // all points are out of bounds, draw nothing
- return;
- } else {
- // 1 & 2 are out
- CLIPX(v1, v3, &ta, bound);
- CLIPX(v2, v3, &tb, bound);
- ClipRightBound(state, &ta, &tb, v3);
- }
- } else {
- if(v3->x < bound){
- // 1 & 3 are out
- CLIPX(v1, v2, &ta, bound);
- CLIPX(v3, v2, &tb, bound);
- ClipRightBound(state, &ta, &tb, v2);
- } else {
- // 1 is out
- CLIPX(v1, v2, &ta, bound);
- CLIPX(v1, v3, &tb, bound);
- ClipRightBound(state, &ta, v2, v3);
- ClipRightBound(state, &tb, &ta, v3);
- }
-
- }
- } else {
- if(v2->x < bound){
- if(v3->x < bound){
- // 2 & 3 are out
- CLIPX(v2, v1, &ta, bound);
- CLIPX(v3, v1, &tb, bound);
- ClipRightBound(state, &ta, &tb, v1);
- return;
- } else {
- // 2 is out
- CLIPX(v2, v1, &ta, bound);
- CLIPX(v2, v3, &tb, bound);
- ClipRightBound(state, &ta, v1, v3);
- ClipRightBound(state, &tb, &ta, v3);
- }
- } else {
- if(v3->x < bound){
- // 3 is out
- CLIPX(v3, v1, &ta, bound);
- CLIPX(v3, v2, &tb, bound);
- ClipRightBound(state, &ta, v1, v2);
- ClipRightBound(state, &tb, &ta, v2);
- } else {
- // all are in
- ClipRightBound(state, v1, v2, v3);
- }
- }
- }
- }
-
-
- static void ClipRightBound(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3)
- {
- TQAVTexture ta, tb;
- float bound = state->viewWidth - boundrySlop;
- /***/
-
- if(v1->x > bound){
- if(v2->x > bound){
- if(v3->x > bound){
- // all points are out of bounds, draw nothing
- return;
- } else {
- // 1 & 2 are out
- CLIPX(v1, v3, &ta, bound);
- CLIPX(v2, v3, &tb, bound);
- ClipTopBound(state, &ta, &tb, v3);
- }
- } else {
- if(v3->x > bound){
- // 1 & 3 are out
- CLIPX(v1, v2, &ta, bound);
- CLIPX(v3, v2, &tb, bound);
- ClipTopBound(state, &ta, &tb, v2);
- } else {
- // 1 is out
- CLIPX(v1, v2, &ta, bound);
- CLIPX(v1, v3, &tb, bound);
- ClipTopBound(state, &ta, v2, v3);
- ClipTopBound(state, &tb, &ta, v3);
- }
-
- }
- } else {
- if(v2->x > bound){
- if(v3->x > bound){
- // 2 & 3 are out
- CLIPX(v2, v1, &ta, bound);
- CLIPX(v3, v1, &tb, bound);
- ClipTopBound(state, &ta, &tb, v1);
- return;
- } else {
- // 2 is out
- CLIPX(v2, v1, &ta, bound);
- CLIPX(v2, v3, &tb, bound);
- ClipTopBound(state, &ta, v1, v3);
- ClipTopBound(state, &tb, &ta, v3);
- }
- } else {
- if(v3->x > bound){
- // 3 is out
- CLIPX(v3, v1, &ta, bound);
- CLIPX(v3, v2, &tb, bound);
- ClipTopBound(state, &ta, v1, v2);
- ClipTopBound(state, &tb, &ta, v2);
- } else {
- // all are in
- ClipTopBound(state, v1, v2, v3);
- }
- }
- }
- }
-
- static void ClipTopBound(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3)
- {
- TQAVTexture ta, tb;
- float bound = 0 + boundrySlop;
- /***/
-
- if(v1->y < bound){
- if(v2->y < bound){
- if(v3->y < bound){
- // all points are out of bounds, draw nothing
- return;
- } else {
- // 1 & 2 are out
- CLIPY(v1, v3, &ta, bound);
- CLIPY(v2, v3, &tb, bound);
- ClipBottomBound(state, &ta, &tb, v3);
- }
- } else {
- if(v3->y < bound){
- // 1 & 3 are out
- CLIPY(v1, v2, &ta, bound);
- CLIPY(v3, v2, &tb, bound);
- ClipBottomBound(state, &ta, &tb, v2);
- } else {
- // 1 is out
- CLIPY(v1, v2, &ta, bound);
- CLIPY(v1, v3, &tb, bound);
- ClipBottomBound(state, &ta, v2, v3);
- ClipBottomBound(state, &tb, &ta, v3);
- }
-
- }
- } else {
- if(v2->y < bound){
- if(v3->y < bound){
- // 2 & 3 are out
- CLIPY(v2, v1, &ta, bound);
- CLIPY(v3, v1, &tb, bound);
- ClipBottomBound(state, &ta, &tb, v1);
- return;
- } else {
- // 2 is out
- CLIPY(v2, v1, &ta, bound);
- CLIPY(v2, v3, &tb, bound);
- ClipBottomBound(state, &ta, v1, v3);
- ClipBottomBound(state, &tb, &ta, v3);
- }
- } else {
- if(v3->y < bound){
- // 3 is out
- CLIPY(v3, v1, &ta, bound);
- CLIPY(v3, v2, &tb, bound);
- ClipBottomBound(state, &ta, v1, v2);
- ClipBottomBound(state, &tb, &ta, v2);
- } else {
- // all are in
- ClipBottomBound(state, v1, v2, v3);
- }
- }
- }
- }
-
- static void ClipBottomBound(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3)
- {
- TQAVTexture ta, tb;
- float bound = state->viewHeight - boundrySlop;
- /***/
-
- if(v1->y > bound){
- if(v2->y > bound){
- if(v3->y > bound){
- // all points are out of bounds, draw nothing
- return;
- } else {
- // 1 & 2 are out
- CLIPY(v1, v3, &ta, bound);
- CLIPY(v2, v3, &tb, bound);
- MyDrawTriTexture(state, &ta, &tb, v3);
- }
- } else {
- if(v3->y > bound){
- // 1 & 3 are out
- CLIPY(v1, v2, &ta, bound);
- CLIPY(v3, v2, &tb, bound);
- MyDrawTriTexture(state, &ta, &tb, v2);
- } else {
- // 1 is out
- CLIPY(v1, v2, &ta, bound);
- CLIPY(v1, v3, &tb, bound);
- MyDrawTriTexture(state, &ta, v2, v3);
- MyDrawTriTexture(state, &tb, &ta, v3);
- }
-
- }
- } else {
- if(v2->y > bound){
- if(v3->y > bound){
- // 2 & 3 are out
- CLIPY(v2, v1, &ta, bound);
- CLIPY(v3, v1, &tb, bound);
- MyDrawTriTexture(state, &ta, &tb, v1);
- return;
- } else {
- // 2 is out
- CLIPY(v2, v1, &ta, bound);
- CLIPY(v2, v3, &tb, bound);
- MyDrawTriTexture(state, &ta, v1, v3);
- MyDrawTriTexture(state, &tb, &ta, v3);
- }
- } else {
- if(v3->y > bound){
- // 3 is out
- CLIPY(v3, v1, &ta, bound);
- CLIPY(v3, v2, &tb, bound);
- MyDrawTriTexture(state, &ta, v1, v2);
- MyDrawTriTexture(state, &tb, &ta, v2);
- } else {
- // all are in
- MyDrawTriTexture(state, v1, v2, v3);
- }
- }
- }
- }
-
-
- static void AppendToVectorList(VList * list, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3)
- {
- if(list->count + 3 > list->bufferSize){
- list->bufferSize += 200;
- // to do: error checking
- list->list = realloc(list->list, sizeof (*list->list) * list->bufferSize);
- CheckMem(list->list);
- }
-
- list->list[list->count] = *v1;
- list->list[list->count + 1] = *v2;
- list->list[list->count + 2] = *v3;
- list->count += 3;
-
- }
-
- static void AppendToTriangleList(TList * list, long vertexIndex)
- {
- if(list->count + 1 > list->bufferSize){
- list->bufferSize += 200;
- // to do: error checking
- list->list = realloc(list->list, sizeof (*list->list) * list->bufferSize);
- CheckMem(list->list);
- }
-
- list->list[list->count].triangleFlags = 0;
- list->list[list->count].vertices[0] = vertexIndex;
- list->list[list->count].vertices[1] = vertexIndex + 1;
- list->list[list->count].vertices[2] = vertexIndex + 2;
- list->count += 1;
-
- }
-
- static void MyDrawTriTexture(MyState *state, TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3)
- {
-
- ClampDifuseColor(v1);
- ClampDifuseColor(v2);
- ClampDifuseColor(v3);
-
- state->triangleCount++;
-
- if(state->useTriMeshes){
- if(state->saveTransTris){
-
- } else {
- AppendToTriangleList(state->currentTList, state->vList.count);
- AppendToVectorList(&state->vList, v1, v2, v3);
- }
- } else {
- QADrawTriTexture(state->drawContext, v1, v2, v3, 0);
- }
- }
-
- static void MyTQAVTextureClip(TQAVTexture * v1, TQAVTexture * v2, TQAVTexture * v3, float weight)
- {
- float weight2 = 1.0 - weight;
-
- /***/
-
- v3->x = v1->x * weight + v2->x * weight2;
- v3->y = v1->y * weight + v2->y * weight2;
- v3->z = v1->z * weight + v2->z * weight2;
-
- v3->invW = v1->invW * weight + v2->invW * weight2;
-
- v3->r = v1->r * weight + v2->r * weight2;
- v3->g = v1->g * weight + v2->g * weight2;
- v3->b = v1->b * weight + v2->b * weight2;
- v3->a = v1->a * weight + v2->a * weight2;
-
- v3->uOverW = v1->uOverW * weight + v2->uOverW * weight2;
- v3->vOverW = v1->vOverW * weight + v2->vOverW * weight2;
-
- v3->kd_r = v1->kd_r * weight + v2->kd_r * weight2;
- v3->kd_g = v1->kd_g * weight + v2->kd_g * weight2;
- v3->kd_b = v1->kd_b * weight + v2->kd_b * weight2;
-
- v3->ks_r = v1->ks_r * weight + v2->ks_r * weight2;
- v3->ks_g = v1->ks_g * weight + v2->ks_g * weight2;
- v3->ks_b = v1->ks_b * weight + v2->ks_b * weight2;
- }
-
-
- static pascal void MyShieldRectNotifyProc(SInt16 left, SInt16 top, SInt16 right, SInt16 bottom, SInt32 refCon)
- {
- #pragma unused(left, top, right, bottom)
-
- MyState *state;
-
- /***********/
-
- state = (MyState *)refCon;
-
- if(state->needsSync){
- state->needsSync = false;
- QASync(state->drawContext);
- }
- }
-
-
-
- static void SetupDrawContext(MyState *state)
- {
- TQADevice myDevice;
- TQAError err;
- Rect r, gr;
- TQARect globalRect;
-
- unsigned long flags;
-
- QDErr e;
- PixMapHandle pm;
- GDHandle gd;
- TQAClip theClip;
- TQAClip *theClipParm;
- RgnHandle clipRegion = NULL;
-
- /*************/
-
- SetPort(state->window); // required for LocalToGlobal();
-
- // r.top, r.left must be 0,0 for now
- r = state->window->portRect;
- r.bottom -= textHeight;
-
- state->viewRect = r;
- state->viewHeight = r.bottom - r.top;
- state->viewWidth = r.right - r.left;
-
- gr = r;
-
- if(state->useTriMeshes){
- // to do: check for fail
- state->tList = calloc(sizeof (TList), textureCount);
- CheckMem(state->tList);
- }
-
- if(state->useMemoryDevice){
- e = NewGWorld(&state->backBuffer, 16, &r, NULL, NULL, keepLocal);
- if(e){
- state->errorMessage = "Error in QADrawContextNew, can't create GWorld";
- state->active = 0;
- goto end;
- }
- pm = GetGWorldPixMap(state->backBuffer);
- e = LockPixels(pm);
- myDevice.deviceType = kQADeviceMemory;
- myDevice.device.memoryDevice.rowBytes = (**pm).rowBytes & 0x3fff;
- myDevice.device.memoryDevice.pixelType = kQAPixel_ARGB16; // apple pci hardware engine cannot draw into a kQAPixel_RGB16
- myDevice.device.memoryDevice.width = r.right;
- myDevice.device.memoryDevice.height = r.bottom;
- myDevice.device.memoryDevice.baseAddr = (**pm).baseAddr;
-
- theClipParm = NULL;
- } else {
- LocalToGlobal(TopLeft(&gr));
- LocalToGlobal(BottomRight(&gr));
-
- gd = GetMaxDevice(&gr);
-
- myDevice.deviceType = kQADeviceGDevice;
- myDevice.device.gDevice = gd;
-
- r = (**gd).gdRect;
-
- /*
- if(gr.left < r.left || gr.top < r.top || gr.bottom > r.bottom || gr.right > r.right){
- state->errorMessage = "Error in QADrawContextNew, the window is not entirely contained inside a gDevice";
- state->active = 0;
- goto end;
- }
- */
-
- state->visRegion = NewRgn();
- CopyRgn(state->window->visRgn, state->visRegion);
-
- clipRegion = CalcGlobalVisRgn(state);
-
- if(clipRegion){
- theClip.clipType = kQAClipRgn;
- theClip.clip.clipRgn = clipRegion;
- theClipParm = &theClip;
- } else {
- theClipParm = NULL;
- }
- }
-
- RectToTQARect(&gr, &globalRect);
-
- flags = 0;
- if(state->doubleBuffer) flags += kQAContext_DoubleBuffer;
- if(state->noZBuffer) flags += kQAContext_NoZBuffer;
-
-
- // note: if a clipping region is given then the apple software engine does double buffering even if you dont tell it to.
- err = QADrawContextNew(&myDevice, &globalRect, theClipParm, state->engine, flags, &state->drawContext);
-
- if(err){
- state->errorMessage = "Error in QADrawContextNew";
- } else {
- //RegisterShieldRect(&gr, MyShieldRectNotifyProc, (long)state, &state->shieldRectCookie);
-
- QASetInt(state->drawContext, kQATag_PerspectiveZ, state->perspectiveZ ? kQAPerspectiveZ_On : kQAPerspectiveZ_Off);
- QASetInt(state->drawContext, kQATag_TextureFilter, state->textureFilter);
- QASetInt(state->drawContext, kQATag_Antialias, state->antialiasing);
- QASetFloat(state->drawContext, kQATag_ColorBG_a, 0);
- QASetFloat(state->drawContext, kQATag_ColorBG_r, 0.2);
- QASetFloat(state->drawContext, kQATag_ColorBG_g, 0.5);
- QASetFloat(state->drawContext, kQATag_ColorBG_b, 1);
- }
-
- state->active = (err == kQANoErr);
- end:
-
- if(clipRegion) DisposeRgn(clipRegion);
-
- if(!state->active){
- DrawErrorMessage(state);
- }
- }
-
-
- static void RectToTQARect(Rect * r, TQARect * r2)
- {
- r2->top = r->top;
- r2->left = r->left;
- r2->bottom = r->bottom;
- r2->right = r->right;
- }
-
-
- static void DeleteDrawContext(MyState *state)
- {
- long x;
-
- /*******/
-
- if(state->drawContext){
- QASync(state->drawContext); // make sure all drawing is completed
-
- if(state->tList){
- for(x = 0; x < textureCount; x++){
- free(state->tList[x].list);
- }
- free(state->tList);
- state->tList = NULL;
- }
-
- if(state->vList.list){
- free(state->vList.list);
- state->vList.list = NULL;
- state->vList.bufferSize = 0;
- }
-
- if(state->backBuffer) DisposeGWorld(state->backBuffer);
- if(state->visRegion) DisposeRgn(state->visRegion);
-
- QADrawContextDelete(state->drawContext);
-
- if(state->shieldRectCookie){
- UnregisterShieldRect(state->shieldRectCookie);
- state->shieldRectCookie = 0;
- }
- }
- }
-
-
- static RgnHandle CalcGlobalVisRgn(MyState * state)
- {
- RgnHandle rgn1, rgn2;
- Point offset;
-
- /*********/
-
- offset.h = offset.v = 0;
-
- SetPort(state->window);
- LocalToGlobal(&offset);
-
- rgn1 = NewRgn();
- rgn2 = NewRgn();
- RectRgn(rgn1, &state->viewRect);
- SectRgn(state->window->visRgn, rgn1, rgn2);
-
- if(EqualRgn(rgn1, rgn2)){ // if the regions are equal then no clipping is required
- DisposeRgn(rgn2);
- rgn2 = NULL;
- } else { // the regions are not equal.
- OffsetRgn(rgn2, offset.h, offset.v); // translate the region to global coordinates
- }
- DisposeRgn(rgn1); // we are done with region 1
-
- return rgn2;
- }
-
-
-
-
-
-
-
-